package cn.imvc.app.models;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Service;

import cn.imvc.app.commons.SystemConfig;
import cn.imvc.app.domains.OrderState;
import cn.imvc.app.entities.GoodsOrder;
import cn.imvc.app.entities.Orders;
import cn.imvc.app.entities.StorageOrder;
import cn.imvc.app.entities.UserSeller;
import cn.imvc.app.repositories.GoodsRepository;
import cn.imvc.app.repositories.StorageOrderRepository;
import cn.imvc.core.ModelUtil;
import cn.imvc.data.domain.ViewRequest;
import cn.imvc.util.ExcelUtils;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

@Service("storageOrderModel")
public class StorageOrderModelImpl implements StorageOrderModel {
	
	@Autowired
	StorageOrderRepository storageOrderRepository;
	@Autowired
	OrdersModel ordersModel;
	@Autowired
	GoodsOrderModel goodsOrderModel;
	@Autowired
	InventoryFlowModel inventoryFlowModel;
	@Autowired
	SystemConfig systemConfig;
	@Autowired
	UserModel userModel;
	@Autowired
	UserSellerModel userSellerModel;
	@Autowired
	BiOrderClientModel biOrderClientModel;
	@Autowired
	MessageModel messageModel;
	
	StorageOrder storageOrder;
	
	private Logger log = Logger.getLogger(StorageOrderModelImpl.class);

	public LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> getRequestMap() {
		// TODO Auto-generated method stub
		return null;
	}

	public Page<StorageOrder> find(ViewRequest viewRequest) {
		if(viewRequest == null){
			viewRequest=new ViewRequest();
		}
		List<UserSeller> userSellers = userSellerModel.getUserSellersByCurUser();
		if(!userSellers.isEmpty()){
			String pre = " and ";
			if(viewRequest.getParams() == null){
				viewRequest.setParams(new HashMap<>());
				pre = "";
			}
			Iterator<UserSeller> iterator = userSellers.iterator();
			StringBuffer sb = new StringBuffer();
			while (iterator.hasNext()) {
				UserSeller userSeller = (UserSeller) iterator.next();
				sb.append(userSeller.getSeller().getId());
				if(iterator.hasNext()){
					sb.append(",");
				}
			}
			viewRequest.getParams().put(pre+" s.seller.id in ("+sb.toString()+") ", " and s.id != -1");
		}
		viewRequest.getSort().put("s.createdAt", "desc");
		viewRequest.getParams().put("_and_s_dot_state_ge_number", OrderState.Delivery.getValue().toString());
		return storageOrderRepository.findAll("distinct s","StorageOrder s inner join s.goodsOrder g",ModelUtil.OrderByIdDesc(viewRequest));
	}

	public StorageOrder get(int id) {
		return storageOrderRepository.getOne(id);
	}

	public StorageOrder save(StorageOrder storageOrder) {
		return storageOrderRepository.saveAndFlush(storageOrder);
	}

	public StorageOrder update(StorageOrder storageOrder) {
		return storageOrderRepository.saveAndFlush(storageOrder);
	}

	public void delete(int id) {
		// TODO Auto-generated method stub

	}

	public void deleteBatch(int[] ids) {
		// TODO Auto-generated method stub

	}

	/**
	 * @author cxy
	 * v0.1更新为代发货，同时更新三级订单，并且更新一级订单状态为代发货（唯一的需要回写上级订单），(不再使用，改为订单部分负责改状态，这里只需要导出订货单)
	 * v0.2只需要将代发货的二级订单导出excel订单即可。（该功能转由吴建新负责）
	 */
	public boolean updateExportOrder(int id) {
		storageOrder = get(id);
		boolean state = false;
/***------------------v0.1---------------------------------->			
			storageOrder.setState(OrderState.Delivery.getValue());
			update(storageOrder);
			//更新一级订单状态为待发货，暂时不用了
//			Orders orders = storageOrder.getOrder();
//			orders.setState(storageOrder.getState());
//			ordersModel.save(orders);
			//同步三级订单
			goodsOrderModel.updateSyncState(storageOrder);
//<----------------------------------------------------------**/		
			//导出订单 
			List<GoodsOrder> goodsOrderList = new ArrayList<GoodsOrder>(storageOrder.getGoodsOrder());
			String[] headline = new String[]{"订单编号", "发件人姓名", "发件人手机", "订单内容","重量(g)","收货地址", "收件人手机", "收件人姓名","订单备注","快递名称","快递单号"};
			String[][] contents = new String[headline.length][goodsOrderList.size()];
			
			for (int i = 0; i < goodsOrderList.size(); i++) {
				contents[0][i] = goodsOrderList.get(i).getCode();
				contents[1][i] = storageOrder.getSeller().getName();
				contents[2][i] = storageOrder.getSeller().getMobPhone();
				contents[3][i] = goodsOrderList.get(i).getTitle()+"     "+goodsOrderList.get(i).getSpec() + "     " + "X"+goodsOrderList.get(i).getNum();
				contents[4][i] = goodsOrderList.get(i).getWeight()+"";
				contents[5][i] = goodsOrderList.get(i).getOrder().getAddress();
				contents[6][i] = goodsOrderList.get(i).getMember().getMobile();
				contents[7][i] = goodsOrderList.get(i).getMember().getName() == null?goodsOrderList.get(i).getMember().getLoginname():goodsOrderList.get(i).getMember().getName();
				contents[8][i] = storageOrder.getRemark();
				contents[9][i] = storageOrder.getExpress().getName();
				contents[10][i] = storageOrder.getExpressCode();
			}
			try {
				ExcelUtils.createExcel(headline, contents, "仓库订单表");
			} catch (RowsExceededException e) {
				e.printStackTrace();
			} catch (WriteException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			state = true; 
		return state;
	}

	/**
	 * 更新为已发货，同时向库存记录表中插入库存修改记录
	 * @throws Exception 
	 */
	public boolean updateDelivered(StorageOrder storageOrder) throws Exception {
		StorageOrder storageOrderTmp = get(storageOrder.getId());
		if(storageOrderTmp.getState() != OrderState.Delivery.getValue()){
			return false;
		}
		BeanUtils.copyProperties(storageOrderTmp, storageOrder,
				new String[] { "id", "express","expressCode","weight","freight","overweightFreight","deliveryTime","receiptEndTime","isDelayed","state" });
		storageOrder.setState(OrderState.Delivered.getValue());
		if((storageOrder.getExpressCode() == null || "".equals(storageOrder.getExpressCode().trim())) && "zzfreetax".equals(storageOrder.getStorage().getStorageType().getCode())){
			//向海关发送订单信息
			String xml = biOrderClientModel.updatePushOrder(storageOrder.getId());
			log.info(xml);
			if(xml.contains("错误") || !xml.contains("<status>0")){
				return false;
			}else{
				update(storageOrder);
				goodsOrderModel.updateSyncState(storageOrder);
				sendMessage(storageOrder);
				return true;
			}
		}else{
			update(storageOrder);
			goodsOrderModel.updateSyncState(storageOrder);
			sendMessage(storageOrder);
			return true;
		}
	}

	public boolean updateSyncState(Orders orders) {
		Set<StorageOrder> storageOrders = orders.getStorageOrder();
		Iterator<StorageOrder> iterator = storageOrders.iterator();
		while (iterator.hasNext()) {
			StorageOrder storageOrder = (StorageOrder) iterator.next();
			StorageOrder storageOrderTmp = get(storageOrder.getId());
			storageOrderTmp.setState(orders.getState());
			update(storageOrderTmp);
			goodsOrderModel.updateSyncState(storageOrderTmp);
		}
		return true;
	}

	@Override
	public List<StorageOrder> findByState(Byte value) {
		return storageOrderRepository.findByState(value);
	}

	@Override
	public void updateAutoReceipt(StorageOrder storageOrder) {
		storageOrder.setState(OrderState.SystemReceipt.getValue());
		storageOrder.setUpdatedAt(new Date());
		storageOrder.setReceiptTime(new Date());
		storageOrderRepository.saveAndFlush(storageOrder);
		//更新下面的订单
		Iterator<GoodsOrder> goodsOrderIterator = storageOrderRepository.getOne(storageOrder.getId()).getGoodsOrder().iterator();
		while (goodsOrderIterator.hasNext()) {
			GoodsOrder goodsOrder = goodsOrderIterator.next();
			if(goodsOrder.getState() == OrderState.Delivered.getValue()){
				goodsOrder.setState(OrderState.SystemReceipt.getValue());
				goodsOrder.setUpdatedAt(new Date());
				goodsOrderModel.update(goodsOrder);
			}
		}
	}

	public List<StorageOrder> findByCode(String orderCode){
		return storageOrderRepository.findByCode(orderCode);
	}
	
	public boolean updateBatchExcelExport(ViewRequest viewRequest) {
		Boolean state = false;
		String expressId  = viewRequest.getParams().get("expressId");
		if(expressId == null || expressId.equals("")){
			expressId = "0";
		}
		String sql = "select * from storage_order s left join orders o on s.orderId = o.id where s.expressId = " + expressId
						+ " and o.payTime >= '" + viewRequest.getParams().get("payTimeBegin")
						+ "' and o.payTime <= '" + viewRequest.getParams().get("payTimeEnd") + "'"
						+ " and s.state = " + OrderState.Delivery.getValue()
						+ " and s.sellerId = " + viewRequest.getParams().get("sellerId");
 		List<StorageOrder> storageOrders = storageOrderRepository.findAllSql(sql, StorageOrder.class);
 		String[] headline = new String[]{"订单编号", "发件人姓名", "发件人手机", "订单内容","重量(g)","收货地址", "收件人手机", "收件人姓名","订单备注","快递名称","快递单号"};
 		String[][] contents = new String[headline.length][storageOrders.size()];
 		if(storageOrders.size() > 0){
 			int i = 0;
 			for (StorageOrder storageOrder : storageOrders) {
 				//导出订单 
 				List<GoodsOrder> goodsOrderList = new ArrayList<GoodsOrder>(storageOrder.getGoodsOrder());
 				
 					contents[0][i] = storageOrder.getCode();
 					contents[1][i] = storageOrder.getSeller().getName();
 					contents[2][i] = storageOrder.getSeller().getMobPhone();
 					contents[3][i] = "";
	 					for (int j = 0; j < goodsOrderList.size(); j++) {
	 					contents[3][i] += "【" + goodsOrderList.get(j).getTitle()+"】  "
	 									+"【" + goodsOrderList.get(j).getSpec() + "】"
	 									+"【" + goodsOrderList.get(j).getNum() + "】\n";
	 					}
 					contents[4][i] = storageOrder.getWeight()+"";
 					contents[5][i] = storageOrder.getOrder().getAddress();
 					contents[6][i] = storageOrder.getMember().getMobile();
 					contents[7][i] = storageOrder.getMember().getName() == null?storageOrder.getMember().getLoginname():storageOrder.getMember().getName();
 					contents[8][i] = storageOrder.getRemark();
 					contents[9][i] = storageOrder.getExpress().getName();
 					contents[10][i] = storageOrder.getExpressCode();
 					i ++;
 				}
 				try {
 					ExcelUtils.createExcel(headline, contents, "仓库订单表");
 					state = true;
 				} catch (RowsExceededException e) {
 					e.printStackTrace();
 				} catch (WriteException e) {
 					e.printStackTrace();
 				} catch (IOException e) {
 					e.printStackTrace();
 				}
 		}else{
 			try {
					ExcelUtils.createExcel(headline, contents, "仓库订单表");
					state = true;
				} catch (RowsExceededException e) {
					e.printStackTrace();
				} catch (WriteException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
 		}
 		return state;
	}

	@Override
	public boolean updateSyncStateByPreState(Orders orders, Byte state) {
		Set<StorageOrder> storageOrders = orders.getStorageOrder();
		Iterator<StorageOrder> iterator = storageOrders.iterator();
		while (iterator.hasNext()) {
			StorageOrder storageOrder = (StorageOrder) iterator.next();
			StorageOrder storageOrderTmp = get(storageOrder.getId());
			if(storageOrderTmp.getState() == state){
				storageOrderTmp.setState(orders.getState());
				update(storageOrderTmp);
				goodsOrderModel.updateSyncStateByPreState(storageOrderTmp,state);
			}
		}
		return true;
	}

	public void updateBiLogisticsNo(String storageOrderCode, String logisticsNo) {
		List<StorageOrder> storageOrders = storageOrderRepository.findByCode(storageOrderCode);
		if(!storageOrders.isEmpty()){
			StorageOrder storageOrder = storageOrders.get(0);
			storageOrder.setExpressCode(logisticsNo);
			storageOrder.setUpdatedAt(new Date());
			storageOrderRepository.saveAndFlush(storageOrder);
		}
	}

	public List<StorageOrder> findByStateAndReceiptEndTimeLessThan(Byte value, Date date) {
		return storageOrderRepository.findByStateAndReceiptEndTimeLessThan(value,date);
	}

	@Override
	public void updateSaveAndSync(StorageOrder storageOrder) {
		storageOrderRepository.saveAndFlush(storageOrder);
		goodsOrderModel.updateSyncState(storageOrder);
		sendMessage(storageOrder);
	}
	
	public void sendMessage(StorageOrder storageOrder){
		try{
		List<String> list=new ArrayList<String>();
		list.add(storageOrder.getExpress().getName());
		list.add(storageOrder.getExpressCode());
		messageModel.sendMessage(storageOrder.getMember(), "deliver", list);
		}catch(Exception e){
			if(storageOrder==null){
				log.error("StorageOrder为空"+e.toString());
			}else{
			log.error("StorageOrderId"+storageOrder.getId()+e.toString());
			}
		}
	}
}
